準備
Step 1. (R
に機能を付け加える)パッケージのインストール(最初だけ)
install.packages("tidyverse")
install.packages("WDI")
Step 2. パッケージを使えるように読み込みます。
library(tidyverse)
── Attaching core tidyverse packages ──────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.3 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.4 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.0
✔ purrr 1.0.2 ── Conflicts ────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(WDI)
Step 3. データを保存するための data
という名前のディレクトリ(フォルダー)を作成します。(最初だけ)
dir.create("data")
Warning: 'data' already exists
Step 4. エラーが生じた時に、調べやすいので、‘システム言語(System
Language)’ を英語にしておきます。(最初だけ)
Sys.setenv(LANG = "en")
Step 5. データを読み込みます。WDI
パッケージをつかうと、簡単に、データを読み込むことができます。わかりやすい名前(gdp、gdppcap)をつけ、人口(pop)も読み込んでおきます。extra
= TRUE
としておくと、使い情報を一緒に読み込むことができます。(すでに、data
に、gdppcap.csv というのがあるときは、Step 5, Step 6
はスキップして、Step 7 だけを実行します。)
df_gdppcap <- WDI(indicator = c(gdp = "NY.GDP.MKTP.PP.KD", pop = "SP.POP.TOTL", gdppcap = "NY.GDP.PCAP.PP.KD"), extra = TRUE)
Step 6. 何度も読み込むのは、時間もかかりますから、最初に作った、data
という、ディレクトリー(フォルダ)に保存しておきます。(すでに、data
に、gdppcap.csv というのがあるときは、Step 5, Step 6
はスキップして、Step 7 だけを実行します。)
write_csv(df_gdppcap, "data/gdppcap.csv")
Step 7. 保存したものを読み込みます。(すでに、data に、gdppcap.csv
というのがあるときは、Step 5, Step 6 はスキップして、Step 7
だけを実行します。)
df_gdppcap <- read_csv("data/gdppcap.csv")
Rows: 16758 Columns: 15── Column specification ───────────────────────────────────────────────────────────────
Delimiter: ","
chr (7): country, iso2c, iso3c, region, capital, income, lending
dbl (6): year, gdp, pop, gdppcap, longitude, latitude
lgl (1): status
date (1): lastupdated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Step 8. データの最初の6行(rows)をみてみます。
head(df_gdppcap)
Step 9.
データの列(columns、変数 variables)はどのようなものがあるかを表示します。
str(df_gdppcap)
spc_tbl_ [16,758 × 15] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ country : chr [1:16758] "Afghanistan" "Afghanistan" "Afghanistan" "Afghanistan" ...
$ iso2c : chr [1:16758] "AF" "AF" "AF" "AF" ...
$ iso3c : chr [1:16758] "AFG" "AFG" "AFG" "AFG" ...
$ year : num [1:16758] 2014 1971 2006 2013 1995 ...
$ status : logi [1:16758] NA NA NA NA NA NA ...
$ lastupdated: Date[1:16758], format: "2023-10-26" "2023-10-26" ...
$ gdp : num [1:16758] 7.02e+10 NA 3.48e+10 6.83e+10 NA ...
$ pop : num [1:16758] 32716210 11015857 25442944 31541209 16418912 ...
$ gdppcap : num [1:16758] 2144 NA 1367 2165 NA ...
$ region : chr [1:16758] "South Asia" "South Asia" "South Asia" "South Asia" ...
$ capital : chr [1:16758] "Kabul" "Kabul" "Kabul" "Kabul" ...
$ longitude : num [1:16758] 69.2 69.2 69.2 69.2 69.2 ...
$ latitude : num [1:16758] 34.5 34.5 34.5 34.5 34.5 ...
$ income : chr [1:16758] "Low income" "Low income" "Low income" "Low income" ...
$ lending : chr [1:16758] "IDA" "IDA" "IDA" "IDA" ...
- attr(*, "spec")=
.. cols(
.. country = col_character(),
.. iso2c = col_character(),
.. iso3c = col_character(),
.. year = col_double(),
.. status = col_logical(),
.. lastupdated = col_date(format = ""),
.. gdp = col_double(),
.. pop = col_double(),
.. gdppcap = col_double(),
.. region = col_character(),
.. capital = col_character(),
.. longitude = col_double(),
.. latitude = col_double(),
.. income = col_character(),
.. lending = col_character()
.. )
- attr(*, "problems")=<externalptr>
Step 10. (ちょっと高度ですが)region, income, lending
には、どのようなものがあるか、みてみます。
df_gdppcap |> select(region, income, lending) |> lapply(unique)
$region
[1] "South Asia" "Aggregates"
[3] "Europe & Central Asia" "Middle East & North Africa"
[5] "East Asia & Pacific" "Sub-Saharan Africa"
[7] "Latin America & Caribbean" "North America"
[9] NA
$income
[1] "Low income" "Aggregates" "Upper middle income"
[4] "Lower middle income" "High income" NA
[7] "Not classified"
$lending
[1] "IDA" "Aggregates" "IBRD" "Not classified"
[5] "Blend" NA
Step 11. 世界の GDP の推移(経年変化)を見てみます。
COUNTRY <- "World"
df_gdppcap |> filter(country == COUNTRY) |> drop_na(gdppcap) |>
ggplot(aes(year, gdp)) + geom_line()

Step 12. 世界の GDP per Capita の推移(経年変化)を見てみます。
COUNTRY <- "World"
df_gdppcap |> filter(country == COUNTRY) |> drop_na(gdppcap) |>
ggplot(aes(year, gdppcap)) + geom_line()

Step 13. 人口の推移(経年変化)もみてみましょう。
COUNTRY <- "World"
df_gdppcap |> filter(country == COUNTRY) |>
ggplot(aes(year, pop)) + geom_line()

Step 14. 2022年の、GDP の多い国から順に並べてみましょう。
arrange(desc(gdp)) とすると、大きい順,
arrange(gdp) とすると小さい順に並びます。
df_gdppcap |> filter(year == 2022, region != "Aggregates") |>
drop_na(gdp) |> arrange(desc(gdp))
Step 15. 2022年の、GDP per Capita
の多い国から順に並べてみましょう。
df_gdppcap |> filter(year == 2022, region != "Aggregates") |>
drop_na(gdppcap) |> arrange(desc(gdppcap))
Step 16. 2022年の、Population(人口)
の多い国から順に並べてみましょう。
df_gdppcap |> filter(year == 2022, region != "Aggregates") |>
drop_na(pop) |> arrange(desc(pop))
Step 17. 2022年の、GDP と Population(人口)
の関係性を、散布図(Scatter Plot)で見てみましょう。
df_gdppcap2 |> filter(year == 2022, region !="Aggregates") |>
drop_na(gdp, pop) |>
ggplot(aes(pop, gdp)) + geom_point()

Step 18. 左横に固まっていましたから、対数表示にしてみます。
df_gdppcap2 |> filter(year == 2022, region !="Aggregates") |>
drop_na(gdp, pop) |>
ggplot(aes(pop, gdp)) + geom_point() +
scale_x_log10() + scale_y_log10()

Step 19.
直線的に増加しているように、見えますから、近似直線(回帰直線といいます)を描いてみます。
df_gdppcap2 |> filter(year == 2022, region !="Aggregates") |>
drop_na(gdp, pop) |>
ggplot(aes(pop, gdp)) + geom_point() +
geom_smooth(method = "lm", formula = 'y ~ x', se = FALSE) +
scale_x_log10() + scale_y_log10()

Step 20.
直線の方程式(Coefficients)や、どのぐらい、当てはまっているか(Residual
R-squared)もみることができます。
df_gdppcap2 |> filter(year == 2022, region !="Aggregates") |>
drop_na(gdp, pop) |> lm(log10(gdp) ~ log10(pop), data = _) |> summary()
Call:
lm(formula = log10(gdp) ~ log10(pop), data = drop_na(filter(df_gdppcap2,
year == 2022, region != "Aggregates"), gdp, pop))
Residuals:
Min 1Q Median 3Q Max
-1.22646 -0.39512 0.03996 0.42553 0.95842
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.45320 0.27485 16.20 <2e-16 ***
log10(pop) 0.94704 0.03998 23.69 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.5117 on 181 degrees of freedom
Multiple R-squared: 0.7561, Adjusted R-squared: 0.7548
F-statistic: 561.2 on 1 and 181 DF, p-value: < 2.2e-16
Step 21. 地域や、収入レベルも色や、形で表示することが可能です。
df_gdppcap2 |> filter(year == 2020, region !="Aggregates") |>
drop_na(gdp, pop) |>
ggplot(aes(pop, gdp, color = region, shape = income)) + geom_point() +
scale_x_log10() + scale_y_log10()

Step 22. これは、一人当たりの GDP
を地域と、人口の情報も入れて表示したものです。
df_gdppcap2 |> filter(year == 2020, region !="Aggregates") |>
drop_na(gdp, gdppcap, pop) |>
ggplot(aes(gdppcap, gdp, color = region, size = pop)) + geom_point() +
scale_x_log10() + scale_y_log10()

Step 23.
他のパッケージを使うと、対話型のグラフを作成することも可能です。
install.packages("plotly")
trying URL 'https://cran.ism.ac.jp/bin/macosx/big-sur-arm64/contrib/4.3/plotly_4.10.3.tgz'
Content type 'application/x-gzip' length 3199222 bytes (3.1 MB)
==================================================
downloaded 3.1 MB
The downloaded binary packages are in
/var/folders/mc/15j2lx113vscs17fxhz_p7400000gn/T//RtmpVDrgz9/downloaded_packages
Step 23. これは、一人当たりの GDP
を地域と、人口の情報も入れて表示したものです。
library(plotly)
test <- df_gdppcap2 |> filter(year == 2020, region !="Aggregates") |> drop_na(gdp, pop) |>
ggplot(aes(color = country, shape = region, pop, gdp)) + geom_point() +
scale_x_log10() + scale_y_log10() + theme(legend.position = "none")
test |> ggplotly()
Warning: The shape palette can deal with a maximum of 6 discrete values because more
than 6 becomes difficult to discriminate; you have 7. Consider specifying
shapes manually if you must have them.
Step 24. 一人当たりのGDP の2022年の分布をみてみましょう。
df_gdppcap |> filter(year == 2022, region != "Aggregates") |> drop_na(gdppcap) |>
ggplot(aes(gdppcap)) + geom_histogram(binwidth = 10000)

Step 25. 対数表示にするとどうなるでううか。
df_gdppcap |> filter(year == 2022, region != "Aggregates") |> drop_na(gdppcap) |>
ggplot(aes(gdppcap)) + geom_histogram(bins = 10) + scale_x_log10()

Step 26. 箱ひげ図で見てみましょう。
df_gdppcap2 |> filter(year == 2020) |> drop_na(gdppcap) |>
filter(income != "Aggregates") |>
ggplot(aes(gdppcap, factor(income, levels = c("High income", "Upper middle income", "Lower middle income", "Low income")), fill = income)) + geom_boxplot() + scale_x_log10() +
labs(y = "") +
theme(legend.position = "none")

LS0tCnRpdGxlOiAi5qW15bqm44Gr6LKn44GX44GE77yB77yfIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgZGZfcHJpbnQ6IHBhZ2VkCiMgICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKIyAgICB0b2M6IHllcwojICAgIHRvY19mbG9hdDogeWVzCi0tLQoKPiBVTklDRUYgW1tMaW5rXShodHRwczovL3d3dy51bmljZWYub3IuanAva29kb21vL3NkZ3MvMTdnb2Fscy8xLXBvdmVydHkvKV0KPgo+IDEuICDkuJbnlYzjgafjga/jgIHlha3kurrjgavkuIDkurrvvIgz5YSENTYwMOS4h+S6uu+8ieOBruWtkOOBqeOCguOBn+OBoeOBjOOAjOalteW6puOBq+OBvuOBmuOBl+OBhOOAjeaaruOCieOBl+OCkuOBl+OBpuOBhOOBvuOBmeOAggoK44Gp44Gu44KI44GG44Gq44OH44O844K/44GL44KJ44CB44GT44Gu44KI44GG44Gq44GT44Go44GM44KP44GL44KL44Gu44Gn44GX44KH44GG44GL44CC44G+44Ga44Gv44CB5qW15bqm44Gu6LKn5Zuw44Go44Gv44CB44Gp44Gu44KI44GG44Gr5a6a576p44GX44Gm44GE44KL44Gu44Gn44GX44KH44GG44GL44CCCgojIyMjIEZhY3QgU2hlZXQ6IEFuIEFkanVzdG1lbnQgdG8gR2xvYmFsIFBvdmVydHkgTGluZXMgW1tMaW5rXShodHRwczovL3d3dy53b3JsZGJhbmsub3JnL2VuL25ld3MvZmFjdHNoZWV0LzIwMjIvMDUvMDIvZmFjdC1zaGVldC1hbi1hZGp1c3RtZW50LXRvLWdsb2JhbC1wb3ZlcnR5LWxpbmVzKV0KClRoZSBXb3JsZCBCYW5rIHVwZGF0ZWQgdGhlIGdsb2JhbCBwb3ZlcnR5IGxpbmVzIGluIFNlcHRlbWJlciAyMDIyLiBUaGUgZGVjaXNpb24sIGFubm91bmNlZCBpbiBNYXksIGZvbGxvd3MgdGhlIHJlbGVhc2UgaW4gMjAyMCBvZiBuZXcgcHVyY2hhc2luZyBwb3dlciBwYXJpdGllcyAoUFBQcyktLS10aGUgbWFpbiBkYXRhIHVzZWQgdG8gY29udmVydCBkaWZmZXJlbnQgY3VycmVuY2llcyBpbnRvIGEgY29tbW9uLCBjb21wYXJhYmxlIHVuaXQgYW5kIGFjY291bnQgZm9yIHByaWNlIGRpZmZlcmVuY2VzIGFjcm9zcyBjb3VudHJpZXMuIFRoZSBuZXcgZXh0cmVtZSBwb3ZlcnR5IGxpbmUgb2YgXCQyLjE1IHBlciBwZXJzb24gcGVyIGRheSwgd2hpY2ggcmVwbGFjZXMgdGhlIFwkMS45MCBwb3ZlcnR5IGxpbmUsIGlzIGJhc2VkIG9uIDIwMTcgUFBQcy4gSGVyZSB5b3UgZmluZCBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgY2hhbmdlIGFuZCB3aGF0IGl0IG1lYW5zIGZvciBtZWFzdXJpbmcgZ2xvYmFsIHBvdmVydHkuCgrkuJbnlYzpioDooYzjga8yMDIy5bm0OeaciOOBq+S4lueVjOOBruiyp+WbsOODqeOCpOODs+OCkuabtOaWsOOBl+OBn+OAgjXmnIjjgavnmbrooajjgZXjgozjgZ/jgZPjga7msbrlrprjga/jgIEyMDIw5bm044Gr5paw6LO86LK35Yqb5bmz5L6h77yIUFBQ77yJ44GM55m66KGo44GV44KM44Gf44GT44Go44KS5Y+X44GR44Gm44Gu44KC44Gu44Gn44GC44KL44CC5paw6LO86LK35Yqb5bmz5L6h77yIUFBQ77yJ44Go44Gv44CB44GV44G+44GW44G+44Gq6YCa6LKo44KS5YWx6YCa44Gu5q+U6LyD5Y+v6IO944Gq5Y2Y5L2N44Gr5aSJ5o+b44GX44CB6LKn5Zuw44Gu56+E5Zuy44KS6Kqs5piO44GZ44KL44Gf44KB44Gr5L2/55So44GV44KM44KL5Li76KaB44Gq44OH44O844K/44Gn44GC44KL44CC5Zu944GU44Go44Gu5L6h5qC85beu44CCMS45MOODieODq+OBruiyp+WbsOe3muOBq+S7o+OCj+OCi+OAgTHkurrlvZPjgZ/jgoox5pel5b2T44Gf44KKMi4xNeODieODq+OBqOOBhOOBhuaWsOOBn+OBqualteW6puOBruiyp+WbsOe3muOBr+OAgTIwMTflubTjga5QUFDjgavln7rjgaXjgYTjgabjgYTjgovjgILjgZPjgZPjgafjga/jgIHjgZPjga7lpInljJbjgajjgZ3jgozjgYzkuJbnlYzjga7osqflm7Djga7muKzlrprjgavkvZXjgpLmhI/lkbPjgZnjgovjgYvjgavplqLjgZnjgovoqbPntLDmg4XloLHjgpLjgZTopqfjgYTjgZ/jgaDjgZHjgb7jgZnjgIIKCuOBneOBk+OBp+OAgeOBk+OBruizvOiyt+WKm+W5s+S+oe+8iFBQUDogcHVyY2hhc2luZyBwb3dlciBwYXJpdGllc++8ieOCkuOBvuOBmuOBr+OAgeiqv+OBueOBpuOBv+OBvuOBl+OCh+OBhuOAguWbveOChOOAgeWcsOWfn+OBlOOBqOOBruOAgUdEUCwgUFBQIOOBqOiogOOCj+OCjOOCi+OCguOBruOBqOOAgeOBneOCjOOCkuOAgeS6uuWPo+OBp+WJsuOBo+OBn+OAgeS4gOS6uuW9k+OBn+OCiuOBruOAgUdEUCBQUFAg44Go6KiA44KP44KM44KL44KC44Gu44Gn44GZ44CCMjAxN+W5tOOCkuWfuua6luOBqOOBl+OBpuOAgeOCpOODs+ODleODrOeOh+OCkuiqv+aVtOOBl+OBpuOBguOCiuOBvuOBmeOAgkdEUCDjga/lm73lhoXnt4/nlJ/nlKPvvIhHcm9zcyBEb21lc3RpYyBQcm9kb2N077yJ44Gu55Wl44Gn44CB5L2V56iu6aGe44GL6KiI566X5pa55rOV44GM44GC44KK44G+44GZ44GM44CB5Z+65pys55qE44Gq57WM5riI5oyH5qiZ44Gn44CB44OJ44Or5o+b566X44GV44KM44Gm44GE44G+44GZ44CCCgotICAgR0RQLCBQUFAgKGNvbnN0YW50IDIwMTcgaW50ZXJuYXRpb25hbCBcJCk6IE5ZLkdEUC5NS1RQLlBQLktECi0gICBHRFAgcGVyIGNhcGl0YSwgUFBQIChjb25zdGFudCAyMDE3IGludGVybmF0aW9uYWwgXCQpOiBOWS5HRFAuUENBUC5QUC5LRAoKR0RQLCBQUFAgKGNvbnN0YW50IDIwMTcgaW50ZXJuYXRpb25hbCBcJCkg44Go44GL44CBR0RQIHBlciBjYXBpdGEsIFBQUCAoY29uc3RhbnQgMjAxNyBpbnRlcm5hdGlvbmFsIFwkKSDjgpLjgIHmjIfmqJnlkI3vvIhJbmRpY2F0b3IgTmFtZe+8ieOBqOOBhOOBhOOAgU5ZLkdEUC5NS1RQLlBQLktEIOOBqOOBi+OAgU5ZLkdEUC5QQ0FQLlBQLktEIOOCkuOAgeaMh+aomeOCs+ODvOODie+8iEluZGljYXRvciBDb2Rl77yJ44Go6KiA44GE44G+44GZ44CC5b6M6ICF44KS44CBV0RJ77yI5LiW55WM6ZaL55m65oyH5qiZ44CBV29ybGQgRGV2ZWxvcG1lbnQgSW5kaWNhdG9y77yJ44Go5ZG844G244GT44Go44KC44GC44KK44G+44GZ44CCCgojIyMg5rqW5YKZCgpTdGVwIDEuIO+8iFIg44Gr5qmf6IO944KS5LuY44GR5Yqg44GI44KL77yJ44OR44OD44Kx44O844K444Gu44Kk44Oz44K544OI44O844Or77yI5pyA5Yid44Gg44GR77yJCgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmluc3RhbGwucGFja2FnZXMoIldESSIpCmBgYAoKU3RlcCAyLiDjg5Hjg4PjgrHjg7zjgrjjgpLkvb/jgYjjgovjgojjgYbjgavoqq3jgb/ovrzjgb/jgb7jgZnjgIIKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShXREkpCmBgYAoKU3RlcCAzLiDjg4fjg7zjgr/jgpLkv53lrZjjgZnjgovjgZ/jgoHjga4gZGF0YSDjgajjgYTjgYblkI3liY3jga7jg4fjgqPjg6zjgq/jg4jjg6rvvIjjg5Xjgqnjg6vjg4Djg7zvvInjgpLkvZzmiJDjgZfjgb7jgZnjgILvvIjmnIDliJ3jgaDjgZHvvIkKCmBgYHtyIGNyZWF0ZS1kaXJzfQpkaXIuY3JlYXRlKCJkYXRhIikKYGBgCgpTdGVwIDQuIOOCqOODqeODvOOBjOeUn+OBmOOBn+aZguOBq+OAgeiqv+OBueOChOOBmeOBhOOBruOBp+OAgSfjgrfjgrnjg4bjg6DoqIDoqp7vvIhTeXN0ZW0gTGFuZ3VhZ2XvvIknIOOCkuiLseiqnuOBq+OBl+OBpuOBiuOBjeOBvuOBmeOAgu+8iOacgOWIneOBoOOBke+8iQoKYGBge3IgZXZhbCA9IEZBTFNFfQpTeXMuc2V0ZW52KExBTkcgPSAiZW4iKQpgYGAKClN0ZXAgNS4g44OH44O844K/44KS6Kqt44G/6L6844G/44G+44GZ44CCV0RJIOODkeODg+OCseODvOOCuOOCkuOBpOOBi+OBhuOBqOOAgeewoeWNmOOBq+OAgeODh+ODvOOCv+OCkuiqreOBv+i+vOOCgOOBk+OBqOOBjOOBp+OBjeOBvuOBmeOAguOCj+OBi+OCiuOChOOBmeOBhOWQjeWJje+8iGdkcOOAgWdkcHBjYXDvvInjgpLjgaTjgZHjgIHkurrlj6PvvIhwb3DvvInjgoLoqq3jgb/ovrzjgpPjgafjgYrjgY3jgb7jgZnjgIJleHRyYSA9IFRSVUUg44Go44GX44Gm44GK44GP44Go44CB5L2/44GE5oOF5aCx44KS5LiA57eS44Gr6Kqt44G/6L6844KA44GT44Go44GM44Gn44GN44G+44GZ44CC77yI44GZ44Gn44Gr44CBZGF0YSDjgavjgIFnZHBwY2FwLmNzdiDjgajjgYTjgYbjga7jgYzjgYLjgovjgajjgY3jga/jgIFTdGVwIDUsIFN0ZXAgNiDjga/jgrnjgq3jg4Pjg5fjgZfjgabjgIFTdGVwIDcg44Gg44GR44KS5a6f6KGM44GX44G+44GZ44CC77yJCgpgYGB7ciBjYWNoZSA9IFRSVUUsIGV2YWwgPSBGQUxTRX0KZGZfZ2RwcGNhcCA8LSBXREkoaW5kaWNhdG9yID0gYyhnZHAgPSAiTlkuR0RQLk1LVFAuUFAuS0QiLCBwb3AgPSAiU1AuUE9QLlRPVEwiLCBnZHBwY2FwID0gIk5ZLkdEUC5QQ0FQLlBQLktEIiksIGV4dHJhID0gVFJVRSkKYGBgCgpTdGVwIDYuIOS9leW6puOCguiqreOBv+i+vOOCgOOBruOBr+OAgeaZgumWk+OCguOBi+OBi+OCiuOBvuOBmeOBi+OCieOAgeacgOWIneOBq+S9nOOBo+OBn+OAgWRhdGEg44Go44GE44GG44CB44OH44Kj44Os44Kv44OI44Oq44O877yI44OV44Kp44Or44OA77yJ44Gr5L+d5a2Y44GX44Gm44GK44GN44G+44GZ44CC77yI44GZ44Gn44Gr44CBZGF0YSDjgavjgIFnZHBwY2FwLmNzdiDjgajjgYTjgYbjga7jgYzjgYLjgovjgajjgY3jga/jgIFTdGVwIDUsIFN0ZXAgNiDjga/jgrnjgq3jg4Pjg5fjgZfjgabjgIFTdGVwIDcg44Gg44GR44KS5a6f6KGM44GX44G+44GZ44CC77yJCgpgYGB7ciBldmFsID0gRkFMU0V9CndyaXRlX2NzdihkZl9nZHBwY2FwLCAiZGF0YS9nZHBwY2FwLmNzdiIpCmBgYAoKU3RlcCA3LiDkv53lrZjjgZfjgZ/jgoLjga7jgpLoqq3jgb/ovrzjgb/jgb7jgZnjgILvvIjjgZnjgafjgavjgIFkYXRhIOOBq+OAgWdkcHBjYXAuY3N2IOOBqOOBhOOBhuOBruOBjOOBguOCi+OBqOOBjeOBr+OAgVN0ZXAgNSwgU3RlcCA2IOOBr+OCueOCreODg+ODl+OBl+OBpuOAgVN0ZXAgNyDjgaDjgZHjgpLlrp/ooYzjgZfjgb7jgZnjgILvvIkKCmBgYHtyfQpkZl9nZHBwY2FwIDwtIHJlYWRfY3N2KCJkYXRhL2dkcHBjYXAuY3N2IikKYGBgCgpTdGVwIDguIOODh+ODvOOCv+OBruacgOWIneOBru+8luihjO+8iHJvd3PvvInjgpLjgb/jgabjgb/jgb7jgZnjgIIKCmBgYHtyfQpoZWFkKGRmX2dkcHBjYXApCmBgYAoKU3RlcCA5LiDjg4fjg7zjgr/jga7liJfvvIhjb2x1bW5z44CB5aSJ5pWw44CAdmFyaWFibGVz77yJ44Gv44Gp44Gu44KI44GG44Gq44KC44Gu44GM44GC44KL44GL44KS6KGo56S644GX44G+44GZ44CCCgpgYGB7cn0Kc3RyKGRmX2dkcHBjYXApCmBgYAoKU3RlcCAxMC4g77yI44Gh44KH44Gj44Go6auY5bqm44Gn44GZ44GM77yJcmVnaW9uLCBpbmNvbWUsIGxlbmRpbmcg44Gr44Gv44CB44Gp44Gu44KI44GG44Gq44KC44Gu44GM44GC44KL44GL44CB44G/44Gm44G/44G+44GZ44CCCgpgYGB7cn0KZGZfZ2RwcGNhcCB8PiBzZWxlY3QocmVnaW9uLCBpbmNvbWUsIGxlbmRpbmcpIHw+IGxhcHBseSh1bmlxdWUpCmBgYAoKU3RlcCAxMS4g5LiW55WM44Gu44CAR0RQIOOBruaOqOenu++8iOe1jOW5tOWkieWMlu+8ieOCkuimi+OBpuOBv+OBvuOBmeOAggoKYGBge3J9CkNPVU5UUlkgPC0gIldvcmxkIgpkZl9nZHBwY2FwIHw+IGZpbHRlcihjb3VudHJ5ID09IENPVU5UUlkpIHw+IGRyb3BfbmEoZ2RwcGNhcCkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIGdkcCkpICsgZ2VvbV9saW5lKCkKYGBgCgpTdGVwIDEyLiDkuJbnlYzjga7jgIBHRFAgcGVyIENhcGl0YSDjga7mjqjnp7vvvIjntYzlubTlpInljJbvvInjgpLopovjgabjgb/jgb7jgZnjgIIKCmBgYHtyfQpDT1VOVFJZIDwtICJXb3JsZCIKZGZfZ2RwcGNhcCB8PiBmaWx0ZXIoY291bnRyeSA9PSBDT1VOVFJZKSB8PiBkcm9wX25hKGdkcHBjYXApIHw+CiAgZ2dwbG90KGFlcyh5ZWFyLCBnZHBwY2FwKSkgKyBnZW9tX2xpbmUoKQpgYGAKClN0ZXAgMTMuIOS6uuWPo+OBruaOqOenu++8iOe1jOW5tOWkieWMlu+8ieOCguOBv+OBpuOBv+OBvuOBl+OCh+OBhuOAggoKYGBge3J9CkNPVU5UUlkgPC0gIldvcmxkIgpkZl9nZHBwY2FwIHw+IGZpbHRlcihjb3VudHJ5ID09IENPVU5UUlkpIHw+CiAgZ2dwbG90KGFlcyh5ZWFyLCBwb3ApKSArIGdlb21fbGluZSgpCmBgYAoKU3RlcCAxNC4gMjAyMuW5tOOBruOAgUdEUCDjga7lpJrjgYTlm73jgYvjgonpoIbjgavkuKbjgbnjgabjgb/jgb7jgZfjgofjgYbjgIIKCmBhcnJhbmdlKGRlc2MoZ2RwKSlgIOOBqOOBmeOCi+OBqOOAgeWkp+OBjeOBhOmghmAsYCBgYXJyYW5nZShnZHApYCDjgajjgZnjgovjgajlsI/jgZXjgYTpoIbjgavkuKbjgbPjgb7jgZnjgIIKCmBgYHtyfQpkZl9nZHBwY2FwIHw+IGZpbHRlcih5ZWFyID09IDIwMjIsIHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoZ2RwKSB8PiBhcnJhbmdlKGRlc2MoZ2RwKSkKYGBgCgpTdGVwIDE1LiAyMDIy5bm044Gu44CBR0RQIHBlciBDYXBpdGEg44Gu5aSa44GE5Zu944GL44KJ6aCG44Gr5Lim44G544Gm44G/44G+44GX44KH44GG44CCCgpgYGB7ciBldmFsID0gRkFMU0V9CmRmX2dkcHBjYXAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMiwgcmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShnZHBwY2FwKSB8PiBhcnJhbmdlKGRlc2MoZ2RwcGNhcCkpCmBgYAoKU3RlcCAxNi4gMjAyMuW5tOOBruOAgVBvcHVsYXRpb27vvIjkurrlj6PvvIkg44Gu5aSa44GE5Zu944GL44KJ6aCG44Gr5Lim44G544Gm44G/44G+44GX44KH44GG44CCCgpgYGB7cn0KZGZfZ2RwcGNhcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIyLCByZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKHBvcCkgfD4gYXJyYW5nZShkZXNjKHBvcCkpCmBgYAoKU3RlcCAxNy4gMjAyMuW5tOOBruOAgUdEUCDjgaggUG9wdWxhdGlvbu+8iOS6uuWPo++8iSDjga7plqLkv4LmgKfjgpLjgIHmlaPluIPlm7PvvIhTY2F0dGVyIFBsb3TvvInjgafopovjgabjgb/jgb7jgZfjgofjgYbjgIIKCmBgYHtyfQpkZl9nZHBwY2FwMiB8PiBmaWx0ZXIoeWVhciA9PSAyMDIyLCByZWdpb24gIT0iQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoZ2RwLCBwb3ApIHw+IAogIGdncGxvdChhZXMocG9wLCBnZHApKSArIGdlb21fcG9pbnQoKQpgYGAKClN0ZXAgMTguIOW3puaoquOBq+WbuuOBvuOBo+OBpuOBhOOBvuOBl+OBn+OBi+OCieOAgeWvvuaVsOihqOekuuOBq+OBl+OBpuOBv+OBvuOBmeOAggoKYGBge3J9CmRmX2dkcHBjYXAyIHw+IGZpbHRlcih5ZWFyID09IDIwMjIsIHJlZ2lvbiAhPSJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShnZHAsIHBvcCkgfD4gCiAgZ2dwbG90KGFlcyhwb3AsIGdkcCkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpCmBgYAoKU3RlcCAxOS4g55u057ea55qE44Gr5aKX5Yqg44GX44Gm44GE44KL44KI44GG44Gr44CB6KaL44GI44G+44GZ44GL44KJ44CB6L+R5Ly855u057ea77yI5Zue5biw55u057ea44Go44GE44GE44G+44GZ77yJ44KS5o+P44GE44Gm44G/44G+44GZ44CCCgpgYGB7cn0KZGZfZ2RwcGNhcDIgfD4gZmlsdGVyKHllYXIgPT0gMjAyMiwgcmVnaW9uICE9IkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKGdkcCwgcG9wKSB8PiAKICBnZ3Bsb3QoYWVzKHBvcCwgZ2RwKSkgKyBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0gJ3kgfiB4Jywgc2UgPSBGQUxTRSkgKwogIHNjYWxlX3hfbG9nMTAoKSArIHNjYWxlX3lfbG9nMTAoKQpgYGAKClN0ZXAgMjAuIOebtOe3muOBruaWueeoi+W8j++8iENvZWZmaWNpZW50c++8ieOChOOAgeOBqeOBruOBkOOCieOBhOOAgeW9k+OBpuOBr+OBvuOBo+OBpuOBhOOCi+OBi++8iFJlc2lkdWFsIFItc3F1YXJlZO+8ieOCguOBv+OCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAggoKYGBge3J9CmRmX2dkcHBjYXAyIHw+IGZpbHRlcih5ZWFyID09IDIwMjIsIHJlZ2lvbiAhPSJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShnZHAsIHBvcCkgfD4gbG0obG9nMTAoZ2RwKSB+IGxvZzEwKHBvcCksIGRhdGEgPSBfKSB8PiBzdW1tYXJ5KCkKYGBgCgpTdGVwIDIxLiDlnLDln5/jgoTjgIHlj47lhaXjg6zjg5njg6vjgoLoibLjgoTjgIHlvaLjgafooajnpLrjgZnjgovjgZPjgajjgYzlj6/og73jgafjgZnjgIIKCmBgYHtyfQpkZl9nZHBwY2FwMiB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwLCByZWdpb24gIT0iQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoZ2RwLCBwb3ApIHw+IAogIGdncGxvdChhZXMocG9wLCBnZHAsIGNvbG9yID0gcmVnaW9uLCBzaGFwZSA9IGluY29tZSkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpCmBgYAoKU3RlcCAyMi4g44GT44KM44Gv44CB5LiA5Lq65b2T44Gf44KK44GuIEdEUCDjgpLlnLDln5/jgajjgIHkurrlj6Pjga7mg4XloLHjgoLlhaXjgozjgabooajnpLrjgZfjgZ/jgoLjga7jgafjgZnjgIIKCmBgYHtyfQpkZl9nZHBwY2FwMiB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwLCByZWdpb24gIT0iQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoZ2RwLCBnZHBwY2FwLCBwb3ApIHw+IAogIGdncGxvdChhZXMoZ2RwcGNhcCwgZ2RwLCBjb2xvciA9IHJlZ2lvbiwgc2l6ZSA9IHBvcCkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpCmBgYAoKU3RlcCAyMy4g5LuW44Gu44OR44OD44Kx44O844K444KS5L2/44GG44Go44CB5a++6Kmx5Z6L44Gu44Kw44Op44OV44KS5L2c5oiQ44GZ44KL44GT44Go44KC5Y+v6IO944Gn44GZ44CCCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikKYGBgCgpTdGVwIDIzLiDjgZPjgozjga/jgIHkuIDkurrlvZPjgZ/jgorjga4gR0RQIOOCkuWcsOWfn+OBqOOAgeS6uuWPo+OBruaDheWgseOCguWFpeOCjOOBpuihqOekuuOBl+OBn+OCguOBruOBp+OBmeOAggoKYGBge3J9CmxpYnJhcnkocGxvdGx5KQp0ZXN0IDwtIGRmX2dkcHBjYXAyIHw+IGZpbHRlcih5ZWFyID09IDIwMjAsIHJlZ2lvbiAhPSJBZ2dyZWdhdGVzIikgfD4gZHJvcF9uYShnZHAsIHBvcCkgfD4gCiAgZ2dwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIHNoYXBlID0gcmVnaW9uLCBwb3AsIGdkcCkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQp0ZXN0IHw+IGdncGxvdGx5KCkKYGBgCgpTdGVwIDI0LiDkuIDkurrlvZPjgZ/jgorjga5HRFAg44GuMjAyMuW5tOOBruWIhuW4g+OCkuOBv+OBpuOBv+OBvuOBl+OCh+OBhuOAggoKYGBge3J9CmRmX2dkcHBjYXAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMiwgcmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gZHJvcF9uYShnZHBwY2FwKSB8PiAKICBnZ3Bsb3QoYWVzKGdkcHBjYXApKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAwMDApCmBgYAoKU3RlcCAyNS4g5a++5pWw6KGo56S644Gr44GZ44KL44Go44Gp44GG44Gq44KL44Gn44GG44GG44GL44CCCgpgYGB7cn0KZGZfZ2RwcGNhcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIyLCByZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiBkcm9wX25hKGdkcHBjYXApIHw+IAogIGdncGxvdChhZXMoZ2RwcGNhcCkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDEwKSArIHNjYWxlX3hfbG9nMTAoKQpgYGAKClN0ZXAgMjYuIOeuseOBsuOBkuWbs+OBp+imi+OBpuOBv+OBvuOBl+OCh+OBhuOAggoKYGBge3J9CmRmX2dkcHBjYXAyIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGRyb3BfbmEoZ2RwcGNhcCkgfD4gCiAgZmlsdGVyKGluY29tZSAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGdncGxvdChhZXMoZ2RwcGNhcCwgZmFjdG9yKGluY29tZSwgbGV2ZWxzID0gYygiSGlnaCBpbmNvbWUiLCAiVXBwZXIgbWlkZGxlIGluY29tZSIsICJMb3dlciBtaWRkbGUgaW5jb21lIiwgIkxvdyBpbmNvbWUiKSksIGZpbGwgPSBpbmNvbWUpKSArIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHkgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCg==